package com.jc.common;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicInteger;

public class OrderNumberGenerator {
    // 业务前缀（可根据业务类型扩展）
    private static final String PREFIX = "C";
    // 序列号位数（3位支持每秒999个订单）
    private static final int SERIAL_NUMBER_LENGTH = 3;
    // 最后时间戳缓存
    private static volatile String lastTimestamp = "";
    // 序列号生成器
    private static final AtomicInteger sequence = new AtomicInteger(0);

    public static synchronized String generate(String prefix) {
        LocalDateTime now = LocalDateTime.now();
        String timestamp = now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));

        // 时间戳变化时重置序列号
        if (!timestamp.equals(lastTimestamp)) {
            sequence.set(0);
            lastTimestamp = timestamp;
        }

        // 生成序列号并补零
        int seq = sequence.incrementAndGet();
        String serialNumber = String.format("%0" + SERIAL_NUMBER_LENGTH + "d", seq);

        // 组合订单号
        return prefix + timestamp + serialNumber;
    }


    /**
     * 生成唯一订单号
     * 格式: 前缀 + yyyyMMddHHmmss + 3位序列号
     * 示例: C202503262143491
     */
    public static synchronized String generate() {
        LocalDateTime now = LocalDateTime.now();
        String timestamp = now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));

        // 时间戳变化时重置序列号
        if (!timestamp.equals(lastTimestamp)) {
            sequence.set(0);
            lastTimestamp = timestamp;
        }

        // 生成序列号并补零
        int seq = sequence.incrementAndGet();
        String serialNumber = String.format("%0" + SERIAL_NUMBER_LENGTH + "d", seq);

        // 组合订单号
        return PREFIX + timestamp + serialNumber;
    }

    // 测试用例
    public static void main(String[] args) {
        // 模拟同一秒内生成多个订单号
        for (int i = 0; i < 5; i++) {
            System.out.println(generate());
        }

        // 模拟不同秒生成订单号
        try {
            Thread.sleep(1000);
            System.out.println(generate());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}